package org.vectrics.imaging.client;


import java.util.*;
import java.util.HashSet;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import org.apache.log4j.*;


class DirectoryManager  {
    private static Category log = Category.getInstance(DirectoryManager.class);
    private boolean initialized = false;
    private Properties firstRecordCache = new Properties();
    private String dataPath;
    //private String fileExtension = FILE_EXT_DEFAULT;
    private HashSet fileExtensions = new HashSet();
    private String directory = null;
    private boolean fileSetDirty = true;
    private SortedSet staticFileSet = new TreeSet();
	private boolean subDirectoriesOnly = false;
    
    protected DirectoryManager() {
    	fileExtensions.add(".*");
    }


	public void clearFileExtensions() {
		fileExtensions.clear();
	}
	
	public void addFileExtension(String role) {
		fileExtensions.add(role);
	}


    public final String getDirectory() {
        return(directory);
    }


    protected void init() {
        if (!initialized) {
            //log.debug("Initializing");
            initialized = true;
        }
    };

    
    public void setDirectory(String directory)
    {
        log.info("File Manager:  Setting directory to: " + directory);
        resetFileList();
        this.directory = directory;
    };

    public void resetFileList() {
        //firstRecordCache.clear();
        fileSetDirty = true;
    }


    synchronized public final void cleanDirectory() {
        log.debug("cleanDirectory() - called");
        Vector fileSet = this.findFileSet();
        log.debug("cleanDirectory() - found file set, now deleting files");
        for (int i = 0; i < fileSet.size(); i++) {
            String fileName = (String)fileSet.elementAt(i);
            File file = new File(getDirectory() + "/" + fileName);
            
            log.debug("cleanDirectory() - Deleting file: " + file.getName());

            if (file.delete() == false) {
                log.error("File could not be deleted for some reason.");
            }
            
            if (file.exists()) {
                log.error("Error deleting file in cleanDirectory() - file still exists after deleting.");
            }
        }
        fileSetDirty = true;
    }
    

    protected final void verifyDirectory() {
        // DO NOT PUT JAVA LOGGING IN THIS METHOD.  CALLED BY APPENDER
        File dir = new File(getDirectory());
        try {
            dir.mkdirs();
        }
        catch (Exception ex) {
            //Ignore exception
            log.error("DirectoryManager.verifyDirectory() - error: " + ex.getMessage(), ex);
        };
    };



    protected  String getFirstRecordCache(String fileName) {
        // Try finding it in cache
        String partialLine = this.firstRecordCache.getProperty(fileName);
        if (partialLine == null) {
            log.debug("getFirstRecordCache() - cached record not found, creating...");
            onFileAdd(fileName);
            partialLine = this.firstRecordCache.getProperty(fileName);
        }
        return(partialLine);
    }

    protected void onFileAdd(String fileName) {
        log.debug("onFileAdd() - called");
        
        // Read first line into properties cache
        String line = firstRecordCache.getProperty(fileName);
        if ((line == null) || (line.length() <= 0)) {
            try {
                FileReader reader = new FileReader(getDirectory() + "/" + fileName);

                BufferedReader bin = new BufferedReader(reader);

                line = bin.readLine();

                //Close input stream
                bin.close();

                reader.close();
                if (line != null) {
                    if (line.length() > 40)
                        line = line.substring(0, 40);
                    if (line.length() > 0) {
                        firstRecordCache.setProperty(fileName, line);
                        log.debug("onFileAdd() - cached first record for file: " + fileName);
                    }
                    else {
                        log.debug("onFileAdd() - file has no records - no caching now.  File = " + fileName);
                    };
                }
                else {
                    if (log.isDebugEnabled())
                        log.debug("onFileAdd() - file has no records - no caching now.  File = " + fileName);
                }
            }
            catch (java.io.FileNotFoundException fe) {
                log.info("onFileAdd() Could not find file: " + fileName);
            }
            catch (java.io.IOException ie) {
                log.info("onFileAdd() - Exception accessing file: " + fileName, ie);
            }
        }

    }


    protected void addFile(String file) {
        // DO NOT PUT JAVA LOGGING IN THIS METHOD - CALLED BY APPENDER
        staticFileSet.add(file);
    }


	public boolean fileIsAcceptable(File file) {
		
		boolean result = false;
		
		if (subDirectoriesOnly) {
			log.debug("fileIsAcceptable() - directory only holds subdir's, checking to see if file is subDir");
			if (file.isDirectory()) {
				log.debug("fileIsAcceptable() - file is a subDir, it is accepted");
				result = true;
			}
			else {
				log.debug("fileIsAcceptable() - file is NOT a subDir, it is rejected");
			}
			
		}
		else {
			log.debug("fileIsAcceptable() - checking file against specified acceptable extensions");
			Iterator extIter = this.fileExtensions.iterator();
		    if (extIter.hasNext() == false)
		    	result = true;
		    else {
		    	while ((result == false) && (extIter.hasNext())) {
			    	String ext = (String)extIter.next();
			    	if ((ext.equals(".*")) || (ext.equals("*"))) {
			    		result = true;
			    	}
			    	else if (file.getName().endsWith(ext)) {
			    		result = true;
			    	}
		    	}
		    }
		}
	    return(result);
	}
	

    synchronized public final Vector findFileSet()
    {
    	log.debug("findFileSet() - method to find files in specified directories");
        staticFileSet.clear();
        firstRecordCache.clear();
        log.debug("findFileSet() - finding all files");
        verifyDirectory();
        File dir = new File(getDirectory());
        File[] fileList = dir.listFiles();

        
        for (int i = 0; i < fileList.length; i++) {
			log.debug("findFileSet() - found file");
            File file = fileList[i];

            int index = 0;
            
            
            boolean fileAcceptable = this.fileIsAcceptable(file);
            if (fileAcceptable) {
                staticFileSet.add(file.getName());
                onFileAdd(file.getName());
                if (log.isEnabledFor(Priority.DEBUG)) {
                    log.debug("findFileSet() - found file: " + file.getName());
                }
            }
            else {
                if (log.isEnabledFor(Priority.DEBUG)) {
                    log.debug("findFileSet() - NOT adding file: " + file.getName() + "   Wrong extention.");
                }
            };
        }
        log.debug("finished - finding log data files");

        // Give calling method it's own copy to avoid concurrency issues.
        Vector fileSetCopy = new Vector();
        fileSetCopy.addAll(staticFileSet);
        log.debug("findFileSet() - finished");
        return(fileSetCopy);
    };


    protected final String getPreviousFile(String fileName)
    {
        String previousFile = null;
        String lastFile = null;
        String currentFile = fileName;
        Vector fileSet = findFileSet();
        Iterator iter = fileSet.iterator();
        boolean done = false;
        while ((iter.hasNext()) && (done == false)) {
            String file = (String)iter.next();
            if (file.equals(fileName)) {
                previousFile = lastFile;
                done = true;
            }
            lastFile = file;
        };
        log.debug("getPreviousFile() called - fileName = " + fileName + "  returned: " + previousFile);
        return(previousFile);
    };

    protected final String getNextFile(String fileName)
    {
        String nextFile = null;
        String currentFile = fileName;
        Vector fileSet = findFileSet();
        Iterator iter = fileSet.iterator();
        boolean done = false;
        while ((iter.hasNext()) && (done == false)) {
            String file = (String)iter.next();
            if (file.equals(fileName)) {
                done = true;
            }
        };
        if (iter.hasNext())
            nextFile = (String)iter.next();

        return(nextFile);
    };



    public void close()
    {
    };

	/**
	 * @return
	 */
	public boolean getSubDirectoriesOnly() {
		return subDirectoriesOnly;
	}

	/**
	 * @param subDirectoriesOnly
	 */
	public void setSubDirectoriesOnly(boolean subDirectoriesOnly) {
		this.subDirectoriesOnly = subDirectoriesOnly;
	}

}